package com.yupi.usercenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yupi.usercenter.model.domain.*;
import com.yupi.usercenter.service.CpuresourceService;
import com.yupi.usercenter.service.MonitorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.NetworkIF;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.util.Util;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class MonitorServiceImpl implements MonitorService {

    @Resource
    private CpuresourceService cpuresourceService;

    @Override
    public Double CPUState() {
        SystemInfo systemInfo = new SystemInfo();
        HardwareAbstractionLayer hardware = systemInfo.getHardware();
        // 获取处理器对象
        CentralProcessor processor = hardware.getProcessor();

        // 获取初始的CPU负载
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        Util.sleep(1000); // 等待一秒钟
        long[] ticks = processor.getSystemCpuLoadTicks();

        // 计算CPU使用率
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long system = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];

        long totalCpu = user + nice + system + idle + iowait + irq + softirq + steal;
        Double cpuUsage = (100d * user / totalCpu);

        //将cpu使用率存入数据库
        Cpuresource cpuresource = new Cpuresource();
        cpuresource.setCpu(cpuUsage);
        cpuresourceService.save(cpuresource);

        log.info("CPU使用率: {}%", cpuUsage);

        return (cpuUsage);
    }

    @Override
    public Double memoryState() {
        // 创建SystemInfo对象
        SystemInfo systemInfo = new SystemInfo();
        // 获取硬件抽象层对象
        HardwareAbstractionLayer hardware = systemInfo.getHardware();
        // 获取内存对象
        GlobalMemory memory = hardware.getMemory();

        // 获取内存信息
        long totalMemory = memory.getTotal();
        long availableMemory = memory.getAvailable();

        // 计算内存使用情况
        long usedMemory = totalMemory - availableMemory;
        return  (double) usedMemory / totalMemory * 100;
    }

    @Override
    public List<Disk> diskState() {
        // 创建SystemInfo对象
        SystemInfo systemInfo = new SystemInfo();
        // 获取操作系统对象
        HardwareAbstractionLayer hardware = systemInfo.getHardware();
        FileSystem fileSystem = systemInfo.getOperatingSystem().getFileSystem();

        // 获取所有文件系统（磁盘分区）
        List<OSFileStore> fileStores = fileSystem.getFileStores();
        List<Disk> diskState = new ArrayList<>();

        for (OSFileStore fileStore : fileStores) {
            Disk disk = new Disk();
            long totalSpace = fileStore.getTotalSpace();
            long usableSpace = fileStore.getUsableSpace();
            long usedSpace = totalSpace - usableSpace;
            double usedPercentage = (double) usedSpace / totalSpace * 100;

            // 输出磁盘使用情况
            disk.setFileSystem(fileStore.getMount());
            disk.setTotalSpace(totalSpace / 1e9);
            disk.setUsedSpace(usedSpace / 1e9);
            disk.setUsableSpace(usableSpace / 1e9);
            disk.setUsage(usedPercentage);
            diskState.add(disk);
        }
        return diskState;
    }

    @Override
    public List<Network> networkState() {
        // 创建SystemInfo对象
        SystemInfo systemInfo = new SystemInfo();
        // 获取硬件抽象层对象
        HardwareAbstractionLayer hardware = systemInfo.getHardware();

        // 获取所有网络接口
        List<NetworkIF> networkIFs = hardware.getNetworkIFs();
        List<Network> networkState = new ArrayList<>();

        for (NetworkIF net : networkIFs) {
            Network network = new Network();
            // 更新网络接口统计数据
            net.updateAttributes();

            // 获取初始数据
            long bytesSentStart = net.getBytesSent();
            long bytesRecvStart = net.getBytesRecv();
            long packetsSentStart = net.getPacketsSent();
            long packetsRecvStart = net.getPacketsRecv();

            // 等待一秒钟
            Util.sleep(1000);

            // 更新网络接口统计数据
            net.updateAttributes();

            // 获取结束数据
            long bytesSentEnd = net.getBytesSent();
            long bytesRecvEnd = net.getBytesRecv();
            long packetsSentEnd = net.getPacketsSent();
            long packetsRecvEnd = net.getPacketsRecv();

            // 计算网络使用情况
            long bytesSent = bytesSentEnd - bytesSentStart;
            long bytesRecv = bytesRecvEnd - bytesRecvStart;
            long packetsSent = packetsSentEnd - packetsSentStart;
            long packetsRecv = packetsRecvEnd - packetsRecvStart;

            // 输出网络使用情况
            network.setNetworkInterface(net.getName());
            network.setBytesSent(bytesSent / 1e9);
            network.setBytesReceived(bytesRecv / 1e9);
            network.setPacketsSent(packetsSent / 1e9);
            network.setPacketsReceived(packetsRecv / 1e9);
            networkState.add(network);
        }
        return networkState;
    }

    @Override
    public Monitor resourceMonitor() {
        Monitor monitor = new Monitor();
        monitor.setCpu(CPUState());
        monitor.setMemory(memoryState());
        monitor.setDisk(diskState());
        monitor.setNetwork(networkState());
        return monitor;
    }

    @Override
    public List<Cpuresource> getCPUState() {
        // 从表中全量查询CPU使用率
        QueryWrapper<Cpuresource> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("time");
        return cpuresourceService.getBaseMapper().selectList(queryWrapper);
    }
}
